/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package xenon3d.vector;

/**
 * This class represents an immutable rgb color based on floating point color
 * components (r = red, g = green, b = blue).
 * @author Volker Everts
 * @version 0.1 - 18.08.2011: Created
 * @version 0.1 - 23.11.2011: Review
 */
public class Color3f {

    // <editor-fold defaultstate="collapsed" desc=" OpenGL Color Constants ">

    /** The black color constant. */
    public static final Color3f BLACK = new Color3f(0.0f, 0.0f, 0.0f);

    /** The ambient color constant. */
    public static final Color3f AMBIENT = new Color3f(0.2f, 0.2f, 0.2f);

    /** The diffuse color constant. */
    public static final Color3f DIFFUSE = new Color3f(0.8f, 0.8f, 0.8f);

    /** The white color constant. */
    public static final Color3f WHITE = new Color3f(1.0f, 1.0f, 1.0f);

    // </editor-fold>

    // <editor-fold defaultstate="collapsed" desc=" Public Fields ">

    /** The red color component. */
    public final float r;

    /** The green color component. */
    public final float g;

    /** The blue color component. */
    public final float b;

    // </editor-fold>

    // <editor-fold defaultstate="collapsed" desc=" Initialization ">

    /**
     * Creates a new Color3f from the specified color components.
     * @param r the red color component
     * @param g the green color component
     * @param b = blue color component
     */
    public Color3f(float r, float g, float b) {
        this.r = r;
        this.g = g;
        this.b = b;
    }

    /**
     * Creates a new Color3f from the specified rgb value.
     * @param rgb the rgb value
     */
    public Color3f(int rgb) {
        r = ((rgb >> 16) & 0xff) / 255.0f;
        g = ((rgb >>  8) & 0xff) / 255.0f;
        b = ((rgb >>  0) & 0xff) / 255.0f;
    }

    /**
     * Creates a new Color3f from the specified java.awt.Color object.
     * @param c the java.awt.Color object
     */
    public Color3f(java.awt.Color c) {
        this(c.getRGB());
    }

    /**
     * Creates a new Color3f by interpolating between two colors, using the
     * specified interpolation weight.
     * @param c1 the first color
     * @param c2 the second color
     * @param weight the interpolation weight
     * @return the interpolated color
     */
    public static Color3f interpolate(Color3f c1, Color3f c2, float weight) {
        float r = (1.0f - weight) * c1.r + weight * c2.r;
        float g = (1.0f - weight) * c1.g + weight * c2.g;
        float b = (1.0f - weight) * c1.b + weight * c2.b;
        return new Color3f(r, g, b);
    }

    // </editor-fold>

    // <editor-fold defaultstate="collapsed" desc=" Public Properties ">

    /**
     * Gets the rgb color components by storing them into the specified float
     * array. The float array must have at least a length of 3.
     * @param fv the float array to store the rgb color components
     */
    public void get(float[] fv) {
        fv[0] = r;
        fv[1] = g;
        fv[2] = b;
    }

    /**
     * Gets the red color component.
     * @return the red component
     */
    public final float getRed() {
        return r;
    }

    /**
     * Gets the green coöor component.
     * @return the green component
     */
    public final float getGreen() {
        return g;
    }

    /**
     * Gets the blue color component.
     * @return the blue component
     */
    public final float getBlue() {
        return b;
    }

    /**
     * Returns true, if this color is epsilon equal to the specified other color.
     * This means, that for every color component the difference is less than the
     * specified positive epsilon value.
     * @param c the other color
     * @param eps the epsilon value, must always be non-negative
     * @return true, if this color is epsilon equal to the other color
     */
    public boolean equals(Color3f c, float eps) {
        if (c == this) return true;
        return FMath.isEqual(r, c.r, eps) && FMath.isEqual(g, c.g, eps) && FMath.isEqual(b, c.b, eps);
    }

    // </editor-fold>

    // <editor-fold defaultstate="collapsed" desc=" Implementation Object ">

    @Override
    public boolean equals(Object obj) {
        if (this == obj) return true;
        if (obj instanceof Color3f) {
            Color3f c = (Color3f) obj;
            return r == c.r && g == c.g && b == c.b;
        }
        return false;
    }

    @Override
    public int hashCode() {
        int hash = 5;
        hash = 79 * hash + Float.floatToIntBits(this.r);
        hash = 79 * hash + Float.floatToIntBits(this.g);
        hash = 79 * hash + Float.floatToIntBits(this.b);
        return hash;
    }

    @Override
    public String toString() {
        return "(" + r + ", " + g + ", " + b + ")";
    }

    // </editor-fold>

} // end class Color3f